{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# **ft** Components"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "_In a nutshell, **ft** components turn Python objects into HTML._"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**ft**, or 'FastTags', are the display components of FastHTML. In fact, the word \"components\" in the context of FastHTML is often synonymous with **ft**. \n",
    "\n",
    "For example, when we look at a FastHTML app, in particular the views, as well as various functions and other objects, we see something like the code snippet below. It's the `return` statement that we want to pay attention to:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fasthtml.common import *\n",
    "\n",
    "def example():\n",
    "    # The code below is a set of ft components\n",
    "    return Div(\n",
    "            H1(\"FastHTML APP\"),\n",
    "            P(\"Let's do this\"),\n",
    "            cls=\"go\"\n",
    "    ) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's go ahead and call our function and print the result:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "```xml\n",
       "<div class=\"go\">\n",
       "  <h1>FastHTML APP</h1>\n",
       "  <p>Let&#x27;s do this</p>\n",
       "</div>\n",
       "\n",
       "```"
      ],
      "text/plain": [
       "['div',\n",
       " (['h1', ('FastHTML APP',), {}], ['p', (\"Let's do this\",), {}]),\n",
       " {'class': 'go'}]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "example()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, when returned to the user from a Python callable, like a function, the ft components are transformed into their string representations of XML or XML-like content such as HTML. More concisely, _ft turns Python objects into HTML_.\n",
    "\n",
    "Now that we know what ft components look and behave like we can begin to understand them. At their most fundamental level, ft components:\n",
    "\n",
    "1. Are Python callables, specifically functions, classes, methods of classes, lambda functions, and anything else called with parenthesis that returns a value.\n",
    "2. Return a sequence of values which has three elements:\n",
    "    1. The tag to be generated\n",
    "    2. The content of the tag, which is a tuple of strings/tuples. If a tuple, it is the three-element structure of an ft component\n",
    "    3. A dictionary of XML attributes and their values\n",
    "3. FastHTML's default ft components words begin with an uppercase letter. Examples include `Title()`, `Ul()`, and `Div()` Custom components have included things like `BlogPost` and `CityMap`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How FastHTML names ft components"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When it comes to naming ft components, FastHTML appears to break from PEP8. Specifically, PEP8 specifies that when naming variables, functions and instantiated classes we use the `snake_case_pattern`. That is to say, lowercase with words separated by underscores. However, FastHTML uses `PascalCase` for ft components.\n",
    "\n",
    "There's a couple of reasons for this:\n",
    "\n",
    "1. ft components can be made from any callable type, so adhering to any one pattern doesn't make much sense\n",
    "2. It makes for easier reading of FastHTML code, as anything that is PascalCase is probably an ft component"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Default **ft** components"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "FastHTML has over 150 **ft** components designed to accelerate web development. Most of these mirror HTML tags such as `<div>`, `<p>`, `<a>`, `<title>`, and more. However, there are some extra tags added, including: \n",
    "\n",
    "- `Titled`, a combination of the `Title()` and `H1()` tags\n",
    "- `Socials`, renders popular social media tags"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The `fasthtml.ft` Namespace"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some people prefer to write code using namespaces while adhering to PEP8. If that's a preference, projects can be coded using the `fasthtml.ft` namespace."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "```xml\n",
       "<ul>\n",
       "  <li>one</li>\n",
       "  <li>two</li>\n",
       "  <li>three</li>\n",
       "</ul>\n",
       "\n",
       "```"
      ],
      "text/plain": [
       "['ul',\n",
       " (['li', ('one',), {}], ['li', ('two',), {}], ['li', ('three',), {}]),\n",
       " {}]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from fasthtml import ft\n",
    "\n",
    "ft.Ul(\n",
    "    ft.Li(\"one\"),\n",
    "    ft.Li(\"two\"),\n",
    "    ft.Li(\"three\")\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Attributes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This example demonstrates many important things to know about how ft components handle attributes.\n",
    "\n",
    "```{.python code-line-numbers=\"true\"}\n",
    "#| echo: False\n",
    "Label( # <1>\n",
    "    \"Choose an option\", \n",
    "    Select(\n",
    "        Option(\"one\", value=\"1\", selected=True), # <2>\n",
    "        Option(\"two\", value=\"2\", selected=False), # <3>\n",
    "        Option(\"three\", value=3),  # <4>\n",
    "        cls=\"selector\",  # <5>\n",
    "        _id=\"counter\", # <6>            \n",
    "        **{'@click':\"alert('Clicked');\"}, # <7>\n",
    "    ),\n",
    "    _for=\"counter\",  # <8>\n",
    ")\n",
    "```\n",
    "\n",
    "1. Line 2 demonstrates that FastHTML appreciates `Label`s surrounding their fields. \n",
    "2. On line 5, we can see that attributes set to the `boolean` value of `True` are rendered with just the name of the attribute. \n",
    "3. On line 6, we demonstrate that attributes set to the `boolean` value of `False` do not appear in the rendered output. \n",
    "4. Line 7 is an example of how integers and other non-string values in the rendered output are converted to strings. \n",
    "5. Line 8 is where we set the HTML class using the `cls` argument. We use `cls` here as `class` is a reserved word in Python. During the rendering process this will be converted to the word \"class\". \n",
    "6. Line 9 demonstrates that any named argument passed into an ft component will have the leading underscore stripped away before rendering. Useful for handling reserved words in Python. \n",
    "7. On line 10 we have an attribute name that cannot be represented as a python variable. In cases like these, we can use an unpacked `dict` to represent these values. \n",
    "8. The use of `_for` on line 12 is another demonstration of an argument having the leading underscore stripped during render. We can also use `fr` as that will be expanded to `for`.\n",
    "\n",
    "This renders the following HTML snippet:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "```xml\n",
       "<label for=\"counter\">\n",
       "Choose an option\n",
       "  <select id=\"counter\" @click=\"alert(&#x27;Clicked&#x27;);\" class=\"selector\" name=\"counter\">\n",
       "    <option value=\"1\" selected>one</option>\n",
       "    <option value=\"2\" >two</option>\n",
       "    <option value=\"3\">three</option>\n",
       "  </select>\n",
       "</label>\n",
       "\n",
       "```"
      ],
      "text/plain": [
       "['label',\n",
       " ('Choose an option',\n",
       "  ['select',\n",
       "   (['option', ('one',), {'value': '1', 'selected': True}],\n",
       "    ['option', ('two',), {'value': '2', 'selected': False}],\n",
       "    ['option', ('three',), {'value': 3}]),\n",
       "   {'id': 'counter',\n",
       "    '@click': \"alert('Clicked');\",\n",
       "    'class': 'selector',\n",
       "    'name': 'counter'}]),\n",
       " {'for': 'counter'}]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Label( # <1>\n",
    "    \"Choose an option\", \n",
    "    Select(\n",
    "        Option(\"one\", value=\"1\", selected=True), # <2>\n",
    "        Option(\"two\", value=\"2\", selected=False), # <3>\n",
    "        Option(\"three\", value=3),  # <4>,\n",
    "        cls=\"selector\",  # <5>\n",
    "        _id=\"counter\", # <6>            \n",
    "        **{'@click':\"alert('Clicked');\"}, # <7>\n",
    "    ),\n",
    "    _for=\"counter\",  # <8>\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining new ft components\n",
    "\n",
    "It is possible and sometimes useful to create your own ft components that generate non-standard tags that are not in the FastHTML library.  FastHTML supports created and defining those new tags flexibly.\n",
    "\n",
    "For more information, see the [Defining new ft components](/ref/defining_xt_component) reference page."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
